home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 197 / os2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-19  |  11.6 KB  |  476 lines

  1. /*    OS2.C:        Operating specific I/O and Spawning functions
  2.             for the OS/2 operating system
  3.             for MicroEMACS 3.9
  4.             (C)opyright 1988 by Daniel M. Lawrence
  5.  
  6. Modifications needed: check that we don't construct command lines and
  7. temporary filenames which are too large for their buffers.
  8.  
  9. */
  10.  
  11. #include        <stdio.h>
  12.  
  13. #include    "estruct.h"
  14. #include    "etype.h"
  15.  
  16. #if    OS2
  17. #define INCL_BASE
  18. #include "os2.h"
  19. #include "elang.h"
  20. #include "edef.h"
  21.  
  22.  
  23. /*
  24.  * Create a subjob with a copy of the command intrepreter in it. When the
  25.  * command interpreter exits, mark the screen as garbage so that you do a full
  26.  * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  27.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  28.  */
  29. spawncli(f, n)
  30. {
  31.     /* don't allow this command if restricted */
  32.     if (restflag)
  33.         return(resterr());
  34.  
  35.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  36.         TTflush();
  37.     TTkclose();
  38.     shell();
  39.     TTkopen();
  40.         sgarbf = TRUE;
  41.         return(TRUE);
  42. }
  43.  
  44.  
  45. /*
  46.  * Run a one-liner in a subjob. When the command returns, wait for a single
  47.  * character to be typed, then mark the screen as garbage so a full repaint is
  48.  * done. Bound to "C-X !".
  49.  */
  50. spawn(f, n)
  51. {
  52.         register int s;
  53.         char line[NLINE];
  54.  
  55.     /* don't allow this command if restricted */
  56.     if (restflag)
  57.         return(resterr());
  58.  
  59.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  60.                 return(s);
  61.     movecursor(term.t_nrow - 1, 0);
  62.     TTkclose();
  63.     system(line);
  64.     TTkopen();
  65.     /* if we are interactive, pause here */
  66.     if (clexec == FALSE) {
  67.             puts(TEXT6);
  68. /*                     "\r\n\n[End]" */
  69.             tgetc();
  70.         }
  71.         sgarbf = TRUE;
  72.         return (TRUE);
  73. }
  74.  
  75.  
  76. /*
  77.  * Run an external program with arguments. When it returns, wait for a single
  78.  * character to be typed, then mark the screen as garbage so a full repaint is
  79.  * done. Bound to "C-X $".
  80.  */
  81.  
  82. execprg(f, n)
  83. {
  84.         register int s;
  85.         char line[NLINE];
  86.  
  87.     /* don't allow this command if restricted */
  88.     if (restflag)
  89.         return(resterr());
  90.  
  91.         if ((s=mlreply("$", line, NLINE)) != TRUE)
  92.                 return(s);
  93.     movecursor(term.t_nrow - 1, 0);
  94.     TTkclose();
  95.         execprog(line);
  96.     TTkopen();
  97.     /* if we are interactive, pause here */
  98.     if (clexec == FALSE) {
  99.             puts(TEXT6);
  100. /*                     "\r\n\n[End]" */
  101.             tgetc();
  102.         }
  103.         sgarbf = TRUE;
  104.         return (TRUE);
  105. }
  106.  
  107. /*
  108.  * Pipe a one line command into a window
  109.  * Bound to ^X @
  110.  * We use a unique temporary file name so that multiple instances of
  111.  * MicroEMACS don't try to use the same file.
  112.  */
  113. pipecmd(f, n)
  114. {
  115.     register WINDOW *wp;    /* pointer to new window */
  116.     register BUFFER *bp;    /* pointer to buffer to zot */
  117.     register char *tmp;    /* ptr to TMP DOS environment variable */
  118.     char line[NLINE];    /* command line send to shell */
  119.     static char bname[] = "command";
  120.     static char filnam[NSTRING];
  121.     char *getenv();
  122.  
  123.     /* don't allow this command if restricted */
  124.     if (restflag)
  125.         return(resterr());
  126.  
  127.     /* get rid of the command output buffer if it exists */
  128.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  129.         /* try to make sure we are off screen */
  130.         wp = wheadp;
  131.         while (wp != NULL) {
  132.             if (wp->w_bufp == bp) {
  133.                 onlywind(FALSE, 1);
  134.                 break;
  135.             }
  136.             wp = wp->w_wndp;
  137.         }
  138.         /* get rid of the existing command buffer */
  139.         if (zotbuf(bp) != TRUE)
  140.             return(FALSE);
  141.     }
  142.  
  143.     /* get the command to pipe in */
  144.         if (mlreply("@", line, NLINE) != TRUE)
  145.                 return(FALSE);
  146.  
  147.     /* Call mktemp() to get a unique filename in the tmp directory. */
  148.     if ((tmp = getenv("TMP")) == NULL)
  149.         filnam[0] = 0;
  150.     else {
  151.         strcpy(filnam, tmp);
  152.         if (filnam[strlen(filnam) - 1] != '\\')
  153.             strcat(filnam, "\\");
  154.         }
  155.     strcat(filnam,"eXXXXXX");
  156.     mktemp(filnam);
  157.  
  158.     /* redirect the command output to the output file */
  159.     strcat(line, " >>");
  160.     strcat(line, filnam);
  161.     movecursor(term.t_nrow - 1, 0);
  162.  
  163.     /* execute the command */
  164.     TTkclose();
  165.     system(line);
  166.     TTkopen();
  167.         sgarbf = TRUE;
  168.  
  169.     /* did the output file get generated? */
  170.     if (access( filnam, 0) != 0)
  171.         return(FALSE);
  172.         
  173.     /* split the current window to make room for the command output */
  174.     if (splitwind(FALSE, 1) == FALSE)
  175.             return(FALSE);
  176.  
  177.     /* and read the stuff in */
  178.     if (getfile(filnam, FALSE) == FALSE)
  179.         return(FALSE);
  180.  
  181.     /* rename the buffer */
  182.     strcpy( curwp->w_bufp->b_bname, "command");
  183.     /* make this window in VIEW mode, update all mode lines */
  184.     curwp->w_bufp->b_mode |= MDVIEW;
  185.     wp = wheadp;
  186.     while (wp != NULL) {
  187.         wp->w_flag |= WFMODE;
  188.         wp = wp->w_wndp;
  189.     }
  190.  
  191.     /* and get rid of the temporary file */
  192.     unlink(filnam);
  193.     return(TRUE);
  194. }
  195.  
  196.  
  197. /*
  198.  * filter a buffer through an external DOS program
  199.  * Bound to ^X #
  200.  * We use unique temporary file names so that multiple instances of
  201.  * MicroEMACS don't try to use the same file.
  202.  */
  203. filter(f, n)
  204.  
  205. {
  206.     register int    s;    /* return status from CLI */
  207.     register BUFFER *bp;    /* pointer to buffer to zot */
  208.     char line[NLINE];    /* command line send to shell */
  209.     char tmpnam[NFILEN];    /* place to store real file name */
  210.     char *tmp;        /* ptr to TMP DOS environment variable */
  211.  
  212.     static char filnam1[NSTRING];
  213.     static char filnam2[NSTRING];
  214.  
  215.     /* don't allow this command if restricted */
  216.     if (restflag)
  217.         return(resterr());
  218.  
  219.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  220.         return(rdonly());    /* we are in read only mode    */
  221.  
  222.     /* get the filter name and its args */
  223.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  224.                 return(s);
  225.  
  226.     /* Call mktemp() to get unique filenames in the tmp directory. */
  227.     if ((tmp = getenv("TMP")) == NULL)
  228.         filnam1[0] = filnam2[0] = 0;
  229.     else {
  230.         strcpy(filnam1, tmp);
  231.         strcpy(filnam2, tmp);
  232.         if (filnam1[strlen(filnam1) - 1] != '\\') {
  233.             strcat(filnam1, "\\");
  234.             strcat(filnam2, "\\");
  235.         }
  236.         }
  237.     strcat(filnam1,"eXXXXXX");
  238.     strcat(filnam2,"eXXXXXX");
  239.     mktemp(filnam1);
  240.     mktemp(filnam2);
  241.                 
  242.     /* setup the proper file names */
  243.     bp = curbp;
  244.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  245.     strcpy(bp->b_fname, filnam1);    /* set it to our new one */
  246.  
  247.     /* write it out, checking for errors */
  248.     if (writeout(filnam1) != TRUE) {
  249.         mlwrite(TEXT2);
  250. /*                      "[Cannot write filter file]" */
  251.         strcpy(bp->b_fname, tmpnam);
  252.         return(FALSE);
  253.     }
  254.  
  255.     strcat(line, " <");        /* construct the command line */
  256.     strcat(line, filnam1);
  257.     strcat(line, " >");
  258.     strcat(line, filnam2);
  259.     
  260.     movecursor(term.t_nrow - 1, 0);
  261.     TTkclose();
  262.         system(line);
  263.     TTkopen();
  264.         sgarbf = TRUE;
  265.     s = TRUE;
  266.  
  267.     /* on failure, escape gracefully */
  268.     if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  269.         mlwrite(TEXT3);
  270. /*                      "[Execution failed]" */
  271.         strcpy(bp->b_fname, tmpnam);
  272.         unlink(filnam1);
  273.         unlink(filnam2);
  274.         return(s);
  275.     }
  276.  
  277.     /* reset file name */
  278.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  279.     bp->b_flag |= BFCHG;        /* flag it as changed */
  280.  
  281.     /* and get rid of the temporary file */
  282.     unlink(filnam1);
  283.     unlink(filnam2);
  284.     return(TRUE);
  285. }
  286.  
  287.  
  288.  
  289. /*    SHELL: Bring up a shell. */
  290.  
  291. shell(void)
  292. {
  293.     char *shell;        /* Name of system command processor */
  294.  
  295.  
  296.     /*  get name of system shell  */
  297.     if ((shell = getenv("COMSPEC")) == NULL) {
  298.         return(FALSE);        /*  No shell located  */
  299.     }
  300.  
  301.     /*
  302.      * We are actually setting up a shell inside a shell here.
  303.      * Is there a better way?
  304.      */
  305.     return(system(shell));
  306. }
  307.  
  308.  
  309.  
  310. execprog( char *cmd)
  311. {
  312.     char         args[NSTRING];        /* args passed to program */
  313.     char        *sp;
  314.     char         failName[1];
  315.     char         prog[NSTRING];        /* name of program */
  316.     USHORT         i;
  317.     PRESULTCODES    *results;
  318.     
  319.  
  320.     /*
  321.      * Parse the command name from the command line and copy it
  322.      * into the prog and args arrays.
  323.      */
  324.     i = 0;
  325.     while (cmd[i]  &&  (cmd[i] != ' ')  &&  (cmd[i] != '\t')) {
  326.         prog[i] = args[i] = cmd[i];
  327.         i++;
  328.     }
  329.     prog[i] = args[i] = 0;        /* terminate with a null */
  330.  
  331.     /* skip whitespace and copy the args */
  332.     while (cmd[i]  &&  ((cmd[i] == ' ')  ||  (cmd[i] == '\t')))
  333.         i++;
  334.     while (cmd[i]) {
  335.         args[i] = cmd[i];
  336.         i++;
  337.     }
  338.     args[i] = args[i + 1] = 0;    /* terminate with 2 nulls */
  339.     
  340.     
  341.     /* look up the program on the path, trying various extentions */
  342.     if ((sp = flook(prog, TRUE)) == NULL)
  343.         if ((sp = flook(strcat(prog, ".exe"), TRUE)) == NULL) {
  344.             strcpy(&prog[strlen(prog)-4], ".com");
  345.             if ((sp = flook(prog, TRUE)) == NULL)
  346.                 return(FALSE);
  347.         }
  348.     strcpy(prog, sp);
  349.  
  350.     /*
  351.      * Execute the program synchronously.  We wait for child
  352.      * to return.
  353.      */
  354.     return (0 == DosExecPgm( &failName, 1, EXEC_SYNC,
  355.                      args, 0, results, prog));
  356. }
  357.  
  358.     
  359. /* return a system dependant string with the current time */
  360.  
  361. char *timeset()
  362.  
  363. {
  364.     register char *sp;    /* temp string pointer */
  365.     char buf[16];        /* time data buffer */
  366.     extern char *ctime();
  367.  
  368.     time(buf);
  369.     sp = ctime(buf);
  370.     sp[strlen(sp)-1] = 0;
  371.     return(sp);
  372. }
  373.  
  374.  
  375.  
  376. /*    extcode:    resolve MSDOS extended character codes
  377.             encoding the proper sequences into emacs
  378.             printable character specifications
  379. */
  380.  
  381. int extcode(c)
  382.  
  383. unsigned c;    /* byte following a zero extended char byte */
  384.  
  385. {
  386.     /* function keys 1 through 9 */
  387.     if (c >= 59 && c < 68)
  388.         return(SPEC | c - 58 + '0');
  389.  
  390.     /* function key 10 */
  391.     if (c == 68)
  392.         return(SPEC | '0');
  393.  
  394.     /* shifted function keys */
  395.     if (c >= 84 && c < 93)
  396.         return(SPEC | SHFT | c - 83 + '0');
  397.     if (c == 93)
  398.         return(SPEC | SHFT | '0');
  399.  
  400.     /* control function keys */
  401.     if (c >= 94 && c < 103)
  402.         return(SPEC | CTRL | c - 93 + '0');
  403.     if (c == 103)
  404.         return(SPEC | CTRL | '0');
  405.  
  406.     /* ALTed function keys */
  407.     if (c >= 104 && c < 113)
  408.         return(SPEC | ALTD | c - 103 + '0');
  409.     if (c == 113)
  410.         return(SPEC | ALTD | '0');
  411.  
  412.     /* ALTed number keys */
  413.     if (c >= 120 && c < 129)
  414.         return(ALTD | c - 119 + '0');
  415.     if (c == 130)
  416.         return(ALTD | '0');
  417.  
  418.     /* some others as well */
  419.     switch (c) {
  420.         case 3:        return(0);        /* null */
  421.         case 15:    return(SHFT | CTRL | 'I');    /* backtab */
  422.  
  423.         case 16:    return(ALTD | 'Q');
  424.         case 17:    return(ALTD | 'W');
  425.         case 18:    return(ALTD | 'E');
  426.         case 19:    return(ALTD | 'R');
  427.         case 20:    return(ALTD | 'T');
  428.         case 21:    return(ALTD | 'Y');
  429.         case 22:    return(ALTD | 'U');
  430.         case 23:    return(ALTD | 'I');
  431.         case 24:    return(ALTD | 'O');
  432.         case 25:    return(ALTD | 'P');
  433.  
  434.         case 30:    return(ALTD | 'A');
  435.         case 31:    return(ALTD | 'S');
  436.         case 32:    return(ALTD | 'D');
  437.         case 33:    return(ALTD | 'F');
  438.         case 34:    return(ALTD | 'G');
  439.         case 35:    return(ALTD | 'H');
  440.         case 36:    return(ALTD | 'J');
  441.         case 37:    return(ALTD | 'K');
  442.         case 38:    return(ALTD | 'L');
  443.  
  444.         case 44:    return(ALTD | 'Z');
  445.         case 45:    return(ALTD | 'X');
  446.         case 46:    return(ALTD | 'C');
  447.         case 47:    return(ALTD | 'V');
  448.         case 48:    return(ALTD | 'B');
  449.         case 49:    return(ALTD | 'N');
  450.         case 50:    return(ALTD | 'M');
  451.  
  452.         case 71:    return(SPEC | '<');    /* HOME */
  453.         case 72:    return(SPEC | 'P');    /* cursor up */
  454.         case 73:    return(SPEC | 'Z');    /* page up */
  455.         case 75:    return(SPEC | 'B');    /* cursor left */
  456.         case 77:    return(SPEC | 'F');    /* cursor right */
  457.         case 79:    return(SPEC | '>');    /* end */
  458.         case 80:    return(SPEC | 'N');    /* cursor down */
  459.         case 81:    return(SPEC | 'V');    /* page down */
  460.         case 82:    return(SPEC | 'C');    /* insert */
  461.         case 83:    return(SPEC | 'D');    /* delete */
  462.         case 115:    return(SPEC | CTRL | 'B');    /* control left */
  463.         case 116:    return(SPEC | CTRL | 'F');    /* control right */
  464.         case 117:    return(SPEC | CTRL | '>');    /* control END */
  465.         case 118:    return(SPEC | CTRL | 'V');    /* control page down */
  466.         case 119:    return(SPEC | CTRL | '<');    /* control HOME */
  467.         case 132:    return(SPEC | CTRL | 'Z');    /* control page up */
  468.     }
  469.  
  470.     return(ALTD | c);
  471. }
  472.  
  473.  
  474. #endif
  475.  
  476.